<?php
namespace Plu\Library\Security;
use Exception;

class Crypto {
    private $encryptionKey; // = "0F10F6CB2F5369C14D14FA07BAD302267901240CC8C845DD2C645FBD149A11C9";
    private $validationKey; // = "C985085862F161091EEEFE30F7DC9D62";

    public function __construct($encryptionKey, $validationKey) {
        $this->encryptionKey = hex2bin($encryptionKey);
        $this->validationKey = hex2bin($validationKey);
    }

    public function updateKeys($encryptionKey, $validationKey) {
        $this->encryptionKey = hex2bin($encryptionKey);
        $this->validationKey = hex2bin($validationKey);
    }

    public function encrypt($clearData) {
        //AES
        $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('AES-256-CBC'));
        $block_size = openssl_cipher_iv_length('AES-256-CBC');
        $padding = $block_size - (strlen($clearData) % $block_size);
        $clearData .= str_repeat(chr($padding), $padding);

        $data = openssl_encrypt($clearData, "AES-256-CBC", $this->encryptionKey, OPENSSL_RAW_DATA, $iv);
        $hashData = $iv . $data;
        //取16位
        $hash = hash_hmac("sha256", $hashData, $this->validationKey);
        $encryptData = bin2hex($iv) . bin2hex($data) . substr($hash, 0, 16);

        return $encryptData;
    }

    public function decrypt($encryptData) {
        if (empty($encryptData)) {
            return false;
        }

        //check encryptData mod == 0
        if ((strlen($encryptData) % 2) != 0) {
            return false;
        }

        $encryptData = hex2bin($encryptData);
        $iv_length = openssl_cipher_iv_length('AES-256-CBC');
        $hash_size = 8;
        $hash = bin2hex(substr($encryptData, -$hash_size));

        $need_hash_data = substr($encryptData, 0, strlen($encryptData) - $hash_size);
        if ($hash != substr(hash_hmac("sha256", $need_hash_data, $this->validationKey), 0, 16)) {
            return false;
        }

        $iv = substr($encryptData, 0, $iv_length);
        $_data = substr($encryptData, $iv_length, strlen($encryptData) - $iv_length - $hash_size);
        $data = openssl_decrypt($_data, "AES-256-CBC", $this->encryptionKey, OPENSSL_RAW_DATA, $iv);

        return $data;
    }

}
